home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’94
/
[√] Distribution Restricted!
/
Brian Hamlin
/
Boom!
/
Boom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-04
|
13KB
|
539 lines
/*
Boom! A quick Hack to Show off PPC graphics (68k version)
@MacHack94 bh noEsis Software Construction
*/
//****************************************************************
// I N C L U D E S
#include <Types.h>
#include <Memory.h>
#include <A4Stuff.h>
#include <SetUpA4.h>
#include <Quickdraw.h>
#include <QDOffscreen.h>
#include <LowMem.h>
#include <Errors.h>
#include <GestaltEqu.h>
#include <Resources.h>
#include <Events.h>
#include <Windows.h>
#include <Sound.h>
#include <MixedMode.h>
#include <fp.h>
#undef NAN
#include <SANE.h>
//****************************************************************
// C O N S T A N T S
#define FALSE false
#define TRUE true
#define NIL 0L
//******************************
// The 68k code goes in a normal INIT resource.
// Be sure this is set to "system heap/locked".
#define kInitRezType 'INIT'
#define kInitRezID 300
#define kMinSystemVersion (0x0603)
//******************************
// from Windows.h:
// pascal Boolean TrackGoAway( WindowPtr theWindow, Point thePt)
// ONEWORDINLINE(0xA91E);
enum {
kTrackGoAwayInfo = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(Boolean)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(WindowPtr)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Point)))
};
typedef pascal Boolean ( *TrackGoAwayFuncPtr ) ( WindowPtr theWindow, Point thePt );
typedef UniversalProcPtr UPP;
// ShowInit
#define kOkOldMac 128
#define kOkPPC 130
#define kNotOldMac 132
#define kNotPPC 134
// explosion constants
struct exVector {
short theta; // 0-360
short speed; // small integer
Point pPos; // current position
Rect pDispR; // current drawn size of 'bit
GWorldPtr tPixGwP; // map 0,0,kSrcPixSiz,kSrcPixSiz
};
typedef struct exVector exVector;
#define kModBits 6
#define kFrameCnt 20
#define kModSpeed 12
#define kSrcPixSiz {0,0,3,3}
#define kScratchSize 265
//****************************************************************
// G L O B A L S
struct NInitGlobals
{
UPP gOrigTrackGoAway; // old Addr
SysEnvRec gSystemInfo;
long gInfo; // 1=68k,2=PPC
Handle gSndHandle;
SndChannelPtr gSndChP;
exVector *gBits;
short gNumBits;
short gFrameCnt;
GWorldPtr gPad; // working image
GWorldPtr gSavPad; // pristine screen copy
};
typedef struct NInitGlobals NInitGlobals;
NInitGlobals *gP;
//****************************************************************
// F O R W A R D S
pascal Boolean nTrackGoAway68k( WindowPtr theWindow, Point thePt);
OSErr DoInitForOldMacs( void);
void PlayBoom(void);
OSErr SetUpSim(void);
void Animate(Point cPt);
void AnimateDone(void);
void ImageFrame(short frameNum, GWorldPtr dstGW, Point exPt);
void PlotImage( GWorldPtr gw, short theta, short speed);
extern void ShowIconFamily(short iconId);
//****************************************************************
void main( void )
{
long oldA4, lRes;
Handle initH = nil; /* Handle to our own INIT resource */
OSErr err = noErr;
oldA4 = SetCurrentA4(); /* Get the proper value of A4 into A4 */
RememberA4(); /* save into self-modifying code */
// Allocate globals struct
gP = (NInitGlobals*) NewPtrSysClear( sizeof(NInitGlobals));
if ( !gP ) {
err = memFullErr;
goto DONE;
}
// Get minimal System Info:
err = SysEnvirons( 1, &gP->gSystemInfo );
if ( err )
goto DONE;
if ( gP->gSystemInfo.systemVersion < kMinSystemVersion ) {
err = -1;
goto DONE;
}
// Prepare to Detach ourselves...
initH = Get1Resource( kInitRezType, kInitRezID );
if ( !initH ) {
err = resNotFound;
goto DONE;
}
// Call Gestalt:
// Gestalt will return an err when SysArc is unimplemented
err = Gestalt( gestaltSysArchitecture, &gP->gInfo );
if ( err) gP->gInfo = gestalt68k;
// Load 'snd ':
// this snd is marked 'sysHeap', so it'll land in the right place,
// and we have to detach anything we want to keep around
gP->gSndHandle = GetResource ('snd ', 128);
DetachResource( gP->gSndHandle);
{ // Make a new SndChannel in the System Heap
THz savZone = GetZone();
SetZone( SystemZone());
err = SndNewChannel( &gP->gSndChP, sampledSynth, initMono, 0);
if ( err != noErr) goto DONE;
SetZone( savZone);
}
err = DoInitForOldMacs(); // sorry, 68k setup only
DONE:
if ( err ) {
ShowIconFamily((gP->gInfo==gestalt68k)?(kNotOldMac):(kNotPPC));
if ( gP )
DisposPtr( (Ptr)gP );
} else {
ShowIconFamily((gP->gInfo==gestalt68k)?(kOkOldMac):(kOkPPC));
DetachResource( initH);
MoveHHi( (Handle)initH); HLock( (Handle)initH);
}
RestoreA4( oldA4 ); /* restore previous value of A4 */
}
//****************************************************************
// DoInitForOldMacs
//****************************************************************
OSErr DoInitForOldMacs( void )
{
long oldA4;
NInitGlobals *locGPtr;
oldA4 = SetUpA4();
locGPtr = gP;
RestoreA4( oldA4 );
locGPtr->gOrigTrackGoAway = NGetTrapAddress( _TrackGoAway, ToolTrap );
NSetTrapAddress( (UPP)nTrackGoAway68k, _TrackGoAway, ToolTrap );
return noErr;
}
//****************************************************************
pascal Boolean nTrackGoAway68k( WindowPtr theWindow, Point thePt )
{
Boolean res;
long oldA4;
GrafPtr tPort;
Point savPt;
TrackGoAwayFuncPtr ptr;
NInitGlobals *locGPtr;
oldA4 = SetUpA4();
locGPtr = gP;
ptr = (TrackGoAwayFuncPtr)locGPtr->gOrigTrackGoAway;
savPt = thePt;
res = ( *ptr )( theWindow, thePt );
if ( res == true) {
if ( locGPtr->gInfo == gestaltPowerPC || *(short*)0x17A) {
THz savZone = GetZone();
SetZone( SystemZone());
if ( SetUpSim() == noErr) {
HideCursor();
Animate( savPt);
AnimateDone();
ShowCursor();
}
SetZone( savZone);
}
}
RestoreA4( oldA4 );
return res;
}
//***********************************************************
void AnimateDone()
{
short cnt;
DisposeGWorld( gP->gPad);
DisposeGWorld( gP->gSavPad);
for ( cnt=0;cnt<gP->gNumBits; cnt++)
DisposeGWorld( gP->gBits[cnt].tPixGwP);
DisposPtr( (Ptr)gP->gBits);
}
//***********************
#define abs(x) ((x>0)?(x):(-x))
OSErr SetUpSim(void)
{
short cnt, prevT;
Rect r = kSrcPixSiz;
Rect r2;
OSErr err;
// init scratch pads
SetRect( &r2, 0, 0, kScratchSize, kScratchSize);
err = NewGWorld( &gP->gPad,8,&r2,0,0,0); // 8 bits only, sorry
if ( err != noErr) return err;
err = NewGWorld( &gP->gSavPad,8,&r2,0,0,0); // 8 bits only, sorry
if ( err != noErr) return err;
// allocate 'bits array
gP->gNumBits = abs(TickCount() % kModBits) + 5; //ok, max+n
gP->gBits = (exVector*)NewPtrClear( gP->gNumBits*sizeof(exVector));
for ( cnt=0;cnt<gP->gNumBits; cnt++){
gP->gBits[cnt].theta = abs((TickCount()*10+cnt) % 360);
gP->gBits[cnt].speed = abs(TickCount() % kModSpeed) + 4;
gP->gBits[cnt].pPos.h = 0;
gP->gBits[cnt].pPos.v = 0;
gP->gBits[cnt].pDispR = r;
err = NewGWorld( &gP->gBits[cnt].tPixGwP,
8,&r,0,0,0);
if ( err != noErr) return err;
// now, based on speed and theta, make an image
PlotImage( gP->gBits[cnt].tPixGwP, gP->gBits[cnt].theta, gP->gBits[cnt].speed);
}
return err;
}
//**************************************************************
//
// Order of Events:
// Prestine PixMap is in gP->gSavPad, working PixMap is in gP->gPad
// For each cell of animation, copy the savPad to workPad,
// Draw all 'bits for this frame, copy gP->gPad to the screen.
//
void Animate( Point cPt)
{
GrafPtr savP; GrafPort dPort;
Rect wR; long t;
short offX=0;
short offY=0;
Point exPt;
PlayBoom();
GetPort( &savP);
OpenPort( &dPort);
SetPort( &dPort);
wR = gP->gPad->portRect;
// if the point is closer to the side of the screen than
// half the width of our buffered draw area, then adjust
// the explosion center
if ( cPt.h > wR.right/2) {
offX = cPt.h - wR.right/2;
exPt.h = wR.right/2;
} else exPt.h = cPt.h;
if ( cPt.v > wR.bottom/2) {
offY = cPt.v - wR.bottom/2;
exPt.v = wR.bottom/2;
} else exPt.v = cPt.v;
OffsetRect( &wR, offX, offY);
// init savMap
CopyBits( (BitMap*)(&(dPort.portBits)),
(BitMap*)(*(gP->gSavPad->portPixMap)),
&wR, &gP->gPad->portRect,
patCopy, 0);
// special effects
{
#define kMax 6
Rect tR, exR; short cnt;
RGBColor tC = {0x0000,0x0000,0x0000};
PenMode( blend); ForeColor( whiteColor);
exR.left = cPt.h - kScratchSize/2;
exR.right = cPt.h + kScratchSize/2;
exR.top = cPt.v - kScratchSize/2;
exR.bottom = cPt.v + kScratchSize/2;
for ( cnt=1; cnt<=kMax; cnt++){
tR = exR;
tC.red += 0x2A00; tC.green += 0x2A00; tC.blue += 0x2A00;
OpColor( &tC);
InsetRect( &tR, cnt*(kScratchSize/kMax), cnt*(kScratchSize/kMax));
PaintOval( &tR);
if ( gP->gInfo == gestaltPowerPC)
Delay( 1, &t);
}
PenNormal(); ForeColor( blackColor);
if ( gP->gInfo == gestaltPowerPC)
Delay( 2, &t);
#undef kMax
}
// animate
for (gP->gFrameCnt=0;gP->gFrameCnt<kFrameCnt;gP->gFrameCnt++) {
// copy savPad to workPad
CopyBits( (BitMap*)(*(gP->gSavPad->portPixMap)),
(BitMap*)(*(gP->gPad->portPixMap)),
&gP->gSavPad->portRect, &gP->gPad->portRect,
patCopy, 0);
ImageFrame(gP->gFrameCnt, gP->gPad, exPt); // image 'bits
// copy workPad to screen
CopyBits( (BitMap*)(*(gP->gPad->portPixMap)),
(BitMap*)(&(dPort.portBits)),
&gP->gPad->portRect, &wR,
patCopy, 0);
if ( gP->gInfo == gestaltPowerPC)
Delay( gP->gFrameCnt/4, &t);
}
// restore screen
CopyBits( (BitMap*)(*(gP->gSavPad->portPixMap)),
(BitMap*)(&(dPort.portBits)),
&gP->gPad->portRect, &wR,
patCopy, 0);
SetPort( savP);
ClosePort( &dPort);
return;
}
//***********************************
void ImageFrame( short frameNum, GWorldPtr dstGW, Point exPt)
{
short posX, posY;
short cnt, f, tSpd;
long t;
Rect srcR = kSrcPixSiz;
Rect dstR;
// r is frameCnt * speed+frameCnt
// posX = r*cos(t)
// posY = r*sin(t)
for (f=frameNum,cnt=0;cnt<gP->gNumBits;cnt++) {
tSpd = gP->gBits[cnt].speed;
posX = (short)(f*(tSpd+cnt)) * cos(gP->gBits[cnt].theta);
posY = (short)(f*(tSpd+cnt)) * sin(gP->gBits[cnt].theta);
dstR = gP->gBits[cnt].pDispR;
dstR.left += exPt.h+posX;
dstR.right += exPt.h+posX;
dstR.top += exPt.v+posY;
dstR.bottom += exPt.v+posY;
CopyBits( (BitMap*)(*(gP->gBits[cnt].tPixGwP->portPixMap)),
(BitMap*)(*(dstGW->portPixMap)),
&srcR, &dstR,
patCopy, 0);
}
}
//**********************
// Create one explosion 'bit
void PlotImage( GWorldPtr gw, short theta, short speed)
{
GWorldPtr savGW;
GDHandle savGdH;
Rect r = kSrcPixSiz;
Point pR1a, pR1b, pR1c;
Point pR2, pO1, pY1a, pY1b;
RGBColor c;
GetGWorld( &savGW, &savGdH);
SetGWorld( gw, 0);
c.red = 0xFFFF; c.green = 0xFFFF; c.blue = 0xFFFF;
RGBForeColor( &c);
PaintRect( &r);
PenNormal();
if ( theta <= 22) { // 22
pR1a.h=1; pR1a.v=2; pR1b.h=2; pR1b.v=1; pR1c.h=1; pR1c.v=0;
pR2.h=2; pR2.v=0; pO1.h=2; pO1.v=2;
pY1a.h=0; pY1a.v=2; pY1b.h=0; pY1b.v=0;
} else if ( theta <= 77) { // 77
pR1a.h=2; pR1a.v=2; pR1b.h=2; pR1b.v=0; pR1c.h=0; pR1c.v=0;
pR2.h=1; pR2.v=0; pO1.h=2; pO1.v=1;
pY1a.h=1; pY1a.v=2; pY1b.h=0; pY1b.v=1;
} else if ( theta <= 112) { // 112
pR1a.h=2; pR1a.v=1; pR1b.h=1; pR1b.v=0; pR1c.h=0; pR1c.v=1;
pR2.h=0; pR2.v=0; pO1.h=2; pO1.v=0;
pY1a.h=2; pY1a.v=2; pY1b.h=0; pY1b.v=2;
} else if ( theta <= 157) { // 157
pR1a.h=2; pR1a.v=0; pR1b.h=0; pR1b.v=0; pR1c.h=0; pR1c.v=2;
pR2.h=0; pR2.v=1; pO1.h=1; pO1.v=0;
pY1a.h=2; pY1a.v=1; pY1b.h=1; pY1b.v=2;
} else if ( theta <= 202) { // 202
pR1a.h=1; pR1a.v=0; pR1b.h=0; pR1b.v=1; pR1c.h=1; pR1c.v=2;
pR2.h=0; pR2.v=2; pO1.h=0; pO1.v=0;
pY1a.h=2; pY1a.v=0; pY1b.h=2; pY1b.v=2;
} else if ( theta <= 247) { // 247
pR1a.h=0; pR1a.v=0; pR1b.h=0; pR1b.v=2; pR1c.h=2; pR1c.v=2;
pR2.h=1; pR2.v=2; pO1.h=0; pO1.v=1;
pY1a.h=1; pY1a.v=0; pY1b.h=2; pY1b.v=1;
} else if ( theta <= 292) { // 292
pR1a.h=0; pR1a.v=1; pR1b.h=1; pR1b.v=2; pR1c.h=2; pR1c.v=1;
pR2.h=2; pR2.v=2; pO1.h=0; pO1.v=2;
pY1a.h=0; pY1a.v=0; pY1b.h=2; pY1b.v=0;
} else if ( theta <= 337) { // 337
pR1a.h=0; pR1a.v=2; pR1b.h=2; pR1b.v=2; pR1c.h=2; pR1c.v=0;
pR2.h=2; pR2.v=1; pO1.h=1; pO1.v=2;
pY1a.h=0; pY1a.v=1; pY1b.h=1; pY1b.v=0;
} else { // +-22
pR1a.h=1; pR1a.v=2; pR1b.h=2; pR1b.v=1; pR1c.h=1; pR1c.v=0;
pR2.h=2; pR2.v=0; pO1.h=2; pO1.v=2;
pY1a.h=0; pY1a.v=2; pY1b.h=0; pY1b.v=0;
}
// NOTE: assumes 'bit pix size of 3x3 !!
c.red = 0xFFFF; c.green = 0x2000; c.blue = 0; // r1
RGBForeColor( &c);
MoveTo( pR1a.h,pR1a.v); Line(0,0);
MoveTo( pR1b.h,pR1c.v); Line(0,0);
MoveTo( pR1c.h,pR1c.v); Line(0,0);
c.red = 0xBAC7; c.green = 0; c.blue = 0; // r2
RGBForeColor( &c);
MoveTo( pR2.h,pR2.v); Line(0,0);
MoveTo( pO1.h,pO1.v); Line(0,0);
c.red = 0xFFFF; c.green = 0xCCC8; c.blue = 0; // o2 (always center)
RGBForeColor( &c);
MoveTo( 1,1); Line(0,0);
c.red = 0xFFFF; c.green = 0xFFFF; c.blue = 0; // y
RGBForeColor( &c);
MoveTo( pY1a.h,pY1a.v); Line(0,0);
MoveTo( pY1b.h,pY1b.v); Line(0,0);
SetGWorld( savGW, savGdH);
return;
}
//***********************************************************
void PlayBoom()
{
OSErr err;
if ( gP->gSndHandle != nil )
err = SndPlay( gP->gSndChP, gP->gSndHandle, true);
}
//***********************************************************************************
// E N D O F L I S T I N G